{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1>Generative Adversarial Network (GAN)</h1>\n",
    "\n",
    "[base paper](https://arxiv.org/pdf/1406.2661v1.pdf)\n",
    "<br>\n",
    "This code is similar to [CNTK DCGAN tutorial](https://github.com/Microsoft/CNTK/blob/master/Tutorials/CNTK_206B_DCGAN.ipynb)\n",
    "except that here a conditional input, dictates the generator what to generate.\n",
    "<br>\n",
    "More descriptive blog post about GANs: https://blog.openai.com/generative-models\n",
    "\n",
    "<h2>Import libraries</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import time\n",
    "import numpy as np\n",
    "import cv2\n",
    "from sklearn.datasets import fetch_mldata\n",
    "from sklearn.preprocessing import OneHotEncoder\n",
    "import shutil\n",
    "import cntk as C"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>parameters and constants</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_set_len = 70000\n",
    "num_class = 10\n",
    "g_input_dim_noise = 100\n",
    "g_hidden_dim = 1024\n",
    "g_output_dim = 784\n",
    "d_input_dim = 784\n",
    "d_hidden_dim = 1024\n",
    "d_output_dim = 1\n",
    "max_epoch = 3000\n",
    "img_h = img_w = 28\n",
    "gstride = dstride = 2\n",
    "gkernel = dkernel = 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>load MNIST data</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "mnist = fetch_mldata('MNIST original')\n",
    "real_img = np.array(mnist.data / 127.5 - 1., dtype=np.float32)\n",
    "enc = OneHotEncoder(dtype=np.float32)\n",
    "enc.fit(mnist.target[:, None])\n",
    "real_code = enc.transform(mnist.target[:, None])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>some helper functions</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def G_sampler(G_model, batch_size, normal=True):\n",
    "    '''\n",
    "    get samples from Generator network\n",
    "\n",
    "    Args:\n",
    "        G_model: Generative model which produces samples\n",
    "        batch_size: number of images sampled from G_model\n",
    "        normal: whether use normal distribution or unofrom as random state\n",
    "\n",
    "    Returns:\n",
    "        z: random state used as Generator input\n",
    "        fake_images: images sampled from Generator\n",
    "        digit_code: conditional code which is fed to Generator\n",
    "    '''\n",
    "    digit_code = enc.transform(np.random.randint(0, num_class, batch_size)[:, None])\n",
    "    if normal:\n",
    "        mu, sigma = 0, 0.33\n",
    "        z = np.random.normal(mu, sigma, (batch_size, g_input_dim_noise))\n",
    "    else:\n",
    "        z = 2.0 * np.random.random((batch_size, g_input_dim_noise)) - 1.0\n",
    "\n",
    "    fake_images = G_model.eval({G_model.find_by_name('G_feature_z'): z,\n",
    "                                G_model.find_by_name('G_feature_code'): digit_code},\n",
    "                               outputs=G_model.find_by_name('G_out'))\n",
    "\n",
    "    return z, fake_images, digit_code\n",
    "\n",
    "\n",
    "def visualize(epoch, batch_size=256, save_model=False):\n",
    "    '''\n",
    "    get samples from G network and save it to samples directory (exception will be occurred if samples directory not exists)\n",
    "\n",
    "    Args:\n",
    "        epoch: epoch number which we are currently at\n",
    "        batch_size: number of images sampled from G\n",
    "        save_model: whether save G and D model or not\n",
    "    '''\n",
    "    global G_net, D_real, G_tensorboard_writer\n",
    "\n",
    "    # check if folder exist\n",
    "    if not os.path.isdir('samples'):\n",
    "        os.mkdir('samples')\n",
    "    p = 'samples/epoch{:05d}'.format(epoch)\n",
    "    if os.path.isdir(p):\n",
    "        shutil.rmtree(p)\n",
    "    os.mkdir(p)\n",
    "    _, samples, codes = G_sampler(G_net, batch_size)\n",
    "    for ind, i in enumerate(zip(samples, codes.toarray())):\n",
    "        code = np.argmax(i[1])\n",
    "        img = (i[0] + 1) * 127\n",
    "        img = img.reshape((28, 28))\n",
    "        cv2.imwrite('samples/epoch{:05d}/epoch{:05d}_ind{:03d}_code{}.jpg'.format(epoch, epoch, ind, code), img)\n",
    "\n",
    "    if save_model:\n",
    "        G_net.save(os.path.join(cwd, 'samples', 'epoch{:05d}', 'G_{:05d}.cntk').format(epoch, epoch))\n",
    "        D_real.save_checkpoint(os.path.join(cwd, 'samples', 'epoch{:05d}', 'D_{:05d}.cntk').format(epoch, epoch))\n",
    "\n",
    "\n",
    "def create_mb_for_D(mb_size):\n",
    "    '''\n",
    "    data generator to train Detector network\n",
    "\n",
    "    Args:\n",
    "        mb_size: number of samples of minibatch\n",
    "\n",
    "    Returns:\n",
    "        real_image, real_code, z (random state) and fake_code all have the same size determined by mb_size\n",
    "    '''\n",
    "    global real_img, real_code\n",
    "\n",
    "    counter = 0\n",
    "    while True:\n",
    "        # create fake batch\n",
    "        z, fake_img, fake_code = G_sampler(G_net, mb_size)\n",
    "\n",
    "        # create real batch\n",
    "        if counter + mb_size < train_set_len:\n",
    "            yield real_img[counter:counter + mb_size].reshape((mb_size, 1, img_h, img_w)), real_code[counter:counter + mb_size], z, fake_code\n",
    "            counter += mb_size\n",
    "        else:\n",
    "            # shuffle\n",
    "            p = np.random.permutation(real_code.shape[0])\n",
    "            real_img, real_code = real_img[p], real_code[p]\n",
    "            counter = 0\n",
    "            yield real_img[counter:counter + mb_size].reshape((mb_size, 1, img_h, img_w)), real_code[counter:counter + mb_size], z, fake_code\n",
    "\n",
    "\n",
    "def create_mb_for_G(mb_size):\n",
    "    '''\n",
    "    data generator to train Generator network\n",
    "\n",
    "    Args:\n",
    "        mb_size: number of samples of minibatch\n",
    "\n",
    "    Returns:\n",
    "        random state and conditional code with the same size of mb_size\n",
    "    '''\n",
    "    while True:\n",
    "        z, _, code = G_sampler(G_net, mb_size)\n",
    "        yield z, code"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>define D and G networks</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def D(x_img, x_code):\n",
    "    '''\n",
    "    Detector network architecture\n",
    "\n",
    "    Args:\n",
    "        x_img: cntk.input_variable represent images to network\n",
    "        x_code: cntk.input_variable represent conditional code to network\n",
    "    '''\n",
    "    def bn_with_leaky_relu(x, leak=0.2):\n",
    "        h = C.layers.BatchNormalization(map_rank=1)(x)\n",
    "        r = C.param_relu(C.constant((np.ones(h.shape) * leak).astype(np.float32)), h)\n",
    "        return r\n",
    "\n",
    "    with C.layers.default_options(init=C.normal(scale=0.02)):\n",
    "\n",
    "        h0 = C.layers.Convolution2D(dkernel, 1, strides=dstride)(x_img)\n",
    "        h0 = bn_with_leaky_relu(h0, leak=0.2)\n",
    "        print('h0 shape :', h0.shape)\n",
    "\n",
    "        h1 = C.layers.Convolution2D(dkernel, 64, strides=dstride)(h0)\n",
    "        h1 = bn_with_leaky_relu(h1, leak=0.2)\n",
    "        print('h1 shape :', h1.shape)\n",
    "\n",
    "        h2 = C.layers.Dense(256, activation=None)(h1)\n",
    "        h2 = bn_with_leaky_relu(h2, leak=0.2)\n",
    "        print('h2 shape :', h2.shape)\n",
    "\n",
    "        h2_aug = C.splice(h2, x_code)\n",
    "\n",
    "        h3 = C.layers.Dense(256, activation=C.relu)(h2_aug)\n",
    "\n",
    "        h4 = C.layers.Dense(1, activation=C.sigmoid, name='D_out')(h3)\n",
    "        print('h3 shape :', h4.shape)\n",
    "\n",
    "        return h4\n",
    "\n",
    "\n",
    "def G(z, code):\n",
    "    '''\n",
    "    Generator network architecture\n",
    "\n",
    "    Args:\n",
    "        z: random state\n",
    "        code: conditional code which the fake images will be generated wrt it\n",
    "    '''\n",
    "    def bn_with_relu(x, activation=C.relu, name='BN'):\n",
    "        h = C.layers.BatchNormalization(map_rank=1, name=name)(x)\n",
    "        return C.relu(h, name=name + '_relu')\n",
    "\n",
    "    i = C.ops.splice(z, code, name='G_splice')\n",
    "    with C.layers.default_options(init=C.normal(scale=0.06)):\n",
    "        print('Generator input shape: ', z.shape)\n",
    "\n",
    "        s_h1, s_w1 = 32, 32\n",
    "        s_h2, s_w2 = 16, 16\n",
    "        s_h4, s_w4 = 8, 8\n",
    "        s_h8, s_w8 = 4, 4\n",
    "        gfc_dim = 128\n",
    "\n",
    "        h0 = C.layers.Dense(gfc_dim, activation=C.ops.tanh, init=C.glorot_normal(scale=1.0), name='fc1')(i)\n",
    "        print('h0 shape', h0.shape)\n",
    "\n",
    "        h1 = C.layers.Dense(gfc_dim, activation=C.ops.tanh, init=C.glorot_normal(scale=1.0), name='fc2')(h0)\n",
    "        print('h1 shape', h0.shape)\n",
    "\n",
    "        h2 = C.layers.Dense([128, s_h8, s_w8], activation=None, name='fc_tensor')(h1)\n",
    "        h2 = bn_with_relu(h2, name='BN1')\n",
    "        print('h2 shape', h2.shape)\n",
    "\n",
    "        h3 = C.layers.ConvolutionTranspose2D(gkernel,\n",
    "                                  num_filters=128,\n",
    "                                  strides=gstride,\n",
    "                                  pad=True,\n",
    "                                  output_shape=(s_h4, s_w4),\n",
    "                                  activation=None,\n",
    "                                  name='transposed_conv1')(h2)\n",
    "        h3 = bn_with_relu(h3, name='BN2')\n",
    "        print('h3 shape', h3.shape)\n",
    "\n",
    "        h4 = C.layers.ConvolutionTranspose2D(gkernel,\n",
    "                                  num_filters=64,\n",
    "                                  strides=gstride,\n",
    "                                  pad=True,\n",
    "                                  output_shape=(s_h2, s_w2),\n",
    "                                  activation=None,\n",
    "                                  name='transposed_conv2')(h3)\n",
    "        print('h4 shape', h4.shape)\n",
    "\n",
    "        h5 = C.layers.ConvolutionTranspose2D(gkernel,\n",
    "                                  num_filters=1,\n",
    "                                  strides=gstride,\n",
    "                                  pad=True,\n",
    "                                  output_shape=(s_h1, s_w1),\n",
    "                                  activation=C.tanh,\n",
    "                                  name='transposed_conv3')(h4)\n",
    "        print('h5 shape :', h5.shape)\n",
    "\n",
    "        # slice extra pixels\n",
    "        h5_w = C.ops.slice(h5, 2, (s_w1 - img_w) // 2, (s_w1 + img_w) // 2, name='cut_w')\n",
    "        h5_w_h = C.ops.slice(h5_w, 1, (s_h1 - img_h) // 2, (s_h1 + img_h) // 2, name='G_out')\n",
    "\n",
    "        return  h5_w_h"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>define computational graph</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Generator input shape:  (100,)\n",
      "h0 shape (128,)\n",
      "h1 shape (128,)\n",
      "h2 shape (128, 4, 4)\n",
      "h3 shape (128, 8, 8)\n",
      "h4 shape (64, 16, 16)\n",
      "h5 shape : (1, 32, 32)\n",
      "h0 shape : (1, 12, 12)\n",
      "h1 shape : (64, 4, 4)\n",
      "h2 shape : (256,)\n",
      "h3 shape : (1,)\n"
     ]
    }
   ],
   "source": [
    "# input nudes\n",
    "G_feature_z = C.input_variable(g_input_dim_noise, name='G_feature_z')\n",
    "G_feature_code = C.input_variable(num_class, name='G_feature_code')\n",
    "D_feature_image = C.input_variable((1, 28, 28), name='D_feature_image')\n",
    "D_feature_code = C.input_variable(num_class, name='D_feature_code')\n",
    "\n",
    "# define networks\n",
    "G_net = G(G_feature_z, G_feature_code)\n",
    "D_real = D(D_feature_image, D_feature_code)\n",
    "D_fake = D_real.clone(method='share', substitutions={D_feature_image: G_net, D_feature_code: G_feature_code})\n",
    "\n",
    "# define loss\n",
    "G_loss = 1. - C.log(D_fake)\n",
    "D_loss = -(C.log(D_real) + C.log(1. - D_fake))\n",
    "\n",
    "# optimizers\n",
    "lr = C.learning_rate_schedule(.0002, C.UnitType.sample)\n",
    "mm = C.momentum_schedule(.5)\n",
    "G_learner = C.adam(parameters=G_net.parameters, lr=lr, momentum=mm)\n",
    "D_learner = C.adam(parameters=D_real.parameters, lr=lr, momentum=mm)\n",
    "\n",
    "# logging\n",
    "G_progress_printer = C.logging.ProgressPrinter(tag='G_training', num_epochs=max_epoch // 100)\n",
    "G_tensorboard_writer = C.logging.TensorBoardProgressWriter(freq=10, log_dir='log_G', model=G_net)\n",
    "D_progress_printer = C.logging.ProgressPrinter(tag='D_training', num_epochs=max_epoch // 100)\n",
    "D_tensorboard_writer = C.logging.TensorBoardProgressWriter(freq=10, log_dir='log_D', model=D_real)\n",
    "\n",
    "# trainer\n",
    "G_trainer = C.Trainer(G_net, (G_loss, None), G_learner, [G_progress_printer, G_tensorboard_writer])\n",
    "D_trainer = C.Trainer(D_real, (D_loss, None), D_learner, [D_progress_printer, D_tensorboard_writer])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>train conditional DCGAN</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/aj/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/core.py:361: UserWarning: your data is of type \"float64\", but your input variable (uid \"Input3\") expects \"<class 'numpy.float32'>\". Please convert your data beforehand to speed up training.\n",
      "  (sample.dtype, var.uid, str(var.dtype)))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Learning rate per 1 samples: 0.0002\n",
      "Learning rate per 1 samples: 0.0002\n",
      "Finished Epoch[1 of 30]: [D_training] loss = 0.682717 * 51200 8.371s (6116.1 samples/s);\n",
      "Finished Epoch[1 of 30]: [G_training] loss = 2.810508 * 25600 8.372s (3057.9 samples/s);\n",
      "Finished Epoch[2 of 30]: [D_training] loss = 0.756222 * 51200 7.517s (6811.3 samples/s);\n",
      "Finished Epoch[2 of 30]: [G_training] loss = 2.773686 * 25600 7.517s (3405.7 samples/s);\n",
      "Finished Epoch[3 of 30]: [D_training] loss = 0.681831 * 51200 7.512s (6815.3 samples/s);\n",
      "Finished Epoch[3 of 30]: [G_training] loss = 2.699018 * 25600 7.512s (3407.7 samples/s);\n",
      "Finished Epoch[4 of 30]: [D_training] loss = 0.662306 * 51200 7.473s (6851.4 samples/s);\n",
      "Finished Epoch[4 of 30]: [G_training] loss = 2.874190 * 25600 7.473s (3425.7 samples/s);\n",
      "Finished Epoch[5 of 30]: [D_training] loss = 0.627350 * 51200 7.503s (6824.2 samples/s);\n",
      "Finished Epoch[5 of 30]: [G_training] loss = 2.983352 * 25600 7.503s (3412.1 samples/s);\n",
      "Finished Epoch[6 of 30]: [D_training] loss = 0.623764 * 51200 7.504s (6823.2 samples/s);\n",
      "Finished Epoch[6 of 30]: [G_training] loss = 3.097039 * 25600 7.504s (3411.6 samples/s);\n",
      "Finished Epoch[7 of 30]: [D_training] loss = 0.630462 * 51200 7.505s (6822.5 samples/s);\n",
      "Finished Epoch[7 of 30]: [G_training] loss = 3.125454 * 25600 7.505s (3411.2 samples/s);\n",
      "Finished Epoch[8 of 30]: [D_training] loss = 0.643468 * 51200 7.472s (6851.9 samples/s);\n",
      "Finished Epoch[8 of 30]: [G_training] loss = 3.136119 * 25600 7.472s (3425.9 samples/s);\n",
      "Finished Epoch[9 of 30]: [D_training] loss = 0.684129 * 51200 7.500s (6826.7 samples/s);\n",
      "Finished Epoch[9 of 30]: [G_training] loss = 3.048051 * 25600 7.500s (3413.3 samples/s);\n",
      "Finished Epoch[10 of 30]: [D_training] loss = 0.701112 * 51200 7.501s (6825.5 samples/s);\n",
      "Finished Epoch[10 of 30]: [G_training] loss = 2.996112 * 25600 7.501s (3412.7 samples/s);\n",
      "Finished Epoch[11 of 30]: [D_training] loss = 0.734280 * 51200 7.500s (6826.2 samples/s);\n",
      "Finished Epoch[11 of 30]: [G_training] loss = 2.937416 * 25600 7.500s (3413.1 samples/s);\n",
      "Finished Epoch[12 of 30]: [D_training] loss = 0.730223 * 51200 7.470s (6854.4 samples/s);\n",
      "Finished Epoch[12 of 30]: [G_training] loss = 2.904194 * 25600 7.470s (3427.2 samples/s);\n",
      "Finished Epoch[13 of 30]: [D_training] loss = 0.737809 * 51200 7.501s (6825.5 samples/s);\n",
      "Finished Epoch[13 of 30]: [G_training] loss = 2.892775 * 25600 7.501s (3412.8 samples/s);\n",
      "Finished Epoch[14 of 30]: [D_training] loss = 0.741639 * 51200 7.501s (6825.6 samples/s);\n",
      "Finished Epoch[14 of 30]: [G_training] loss = 2.854200 * 25600 7.501s (3412.8 samples/s);\n",
      "Finished Epoch[15 of 30]: [D_training] loss = 0.765311 * 51200 7.467s (6856.9 samples/s);\n",
      "Finished Epoch[15 of 30]: [G_training] loss = 2.848305 * 25600 7.467s (3428.4 samples/s);\n",
      "Finished Epoch[16 of 30]: [D_training] loss = 0.776507 * 51200 7.500s (6826.9 samples/s);\n",
      "Finished Epoch[16 of 30]: [G_training] loss = 2.806709 * 25600 7.500s (3413.5 samples/s);\n",
      "Finished Epoch[17 of 30]: [D_training] loss = 0.792416 * 51200 7.499s (6827.8 samples/s);\n",
      "Finished Epoch[17 of 30]: [G_training] loss = 2.742251 * 25600 7.499s (3413.9 samples/s);\n",
      "Finished Epoch[18 of 30]: [D_training] loss = 0.841636 * 51200 7.503s (6823.5 samples/s);\n",
      "Finished Epoch[18 of 30]: [G_training] loss = 2.731426 * 25600 7.503s (3411.7 samples/s);\n",
      "Finished Epoch[19 of 30]: [D_training] loss = 0.864238 * 51200 7.467s (6856.8 samples/s);\n",
      "Finished Epoch[19 of 30]: [G_training] loss = 2.661473 * 25600 7.467s (3428.4 samples/s);\n",
      "Finished Epoch[20 of 30]: [D_training] loss = 0.904774 * 51200 7.502s (6824.5 samples/s);\n",
      "Finished Epoch[20 of 30]: [G_training] loss = 2.612339 * 25600 7.502s (3412.3 samples/s);\n",
      "Finished Epoch[21 of 30]: [D_training] loss = 0.936342 * 51200 7.506s (6821.6 samples/s);\n",
      "Finished Epoch[21 of 30]: [G_training] loss = 2.548476 * 25600 7.506s (3410.7 samples/s);\n",
      "Finished Epoch[22 of 30]: [D_training] loss = 0.959122 * 51200 7.515s (6813.3 samples/s);\n",
      "Finished Epoch[22 of 30]: [G_training] loss = 2.496412 * 25600 7.515s (3406.7 samples/s);\n",
      "Finished Epoch[23 of 30]: [D_training] loss = 0.998110 * 51200 7.509s (6818.3 samples/s);\n",
      "Finished Epoch[23 of 30]: [G_training] loss = 2.470499 * 25600 7.509s (3409.1 samples/s);\n",
      "Finished Epoch[24 of 30]: [D_training] loss = 1.005829 * 51200 7.534s (6795.9 samples/s);\n",
      "Finished Epoch[24 of 30]: [G_training] loss = 2.416253 * 25600 7.534s (3398.0 samples/s);\n",
      "Finished Epoch[25 of 30]: [D_training] loss = 1.023046 * 51200 7.532s (6797.4 samples/s);\n",
      "Finished Epoch[25 of 30]: [G_training] loss = 2.414770 * 25600 7.532s (3398.7 samples/s);\n",
      "Finished Epoch[26 of 30]: [D_training] loss = 1.037944 * 51200 7.500s (6826.5 samples/s);\n",
      "Finished Epoch[26 of 30]: [G_training] loss = 2.323481 * 25600 7.500s (3413.3 samples/s);\n",
      "Finished Epoch[27 of 30]: [D_training] loss = 1.043260 * 51200 7.538s (6791.9 samples/s);\n",
      "Finished Epoch[27 of 30]: [G_training] loss = 2.320578 * 25600 7.538s (3395.9 samples/s);\n",
      "Finished Epoch[28 of 30]: [D_training] loss = 1.037610 * 51200 7.534s (6795.9 samples/s);\n",
      "Finished Epoch[28 of 30]: [G_training] loss = 2.320159 * 25600 7.534s (3398.0 samples/s);\n",
      "Finished Epoch[29 of 30]: [D_training] loss = 1.051200 * 51200 7.537s (6792.9 samples/s);\n",
      "Finished Epoch[29 of 30]: [G_training] loss = 2.289761 * 25600 7.537s (3396.5 samples/s);\n",
      "Finished Epoch[30 of 30]: [D_training] loss = 1.058925 * 51200 7.503s (6824.2 samples/s);\n",
      "Finished Epoch[30 of 30]: [G_training] loss = 2.293206 * 25600 7.503s (3412.1 samples/s);\n",
      "training conditional DCGAN takes 225.98364925384521(secs) long\n"
     ]
    }
   ],
   "source": [
    "# create loop\n",
    "t0 = time.time()\n",
    "D_DS = create_mb_for_D(256)\n",
    "G_DS = create_mb_for_G(256)\n",
    "for epoch in range(max_epoch):\n",
    "    # train D for k steps\n",
    "    k = 2\n",
    "    for i in range(k):\n",
    "        D_mb = next(D_DS)\n",
    "        input_map = {D_feature_image: D_mb[0], D_feature_code: D_mb[1], G_feature_z: D_mb[2], G_feature_code: D_mb[3]}\n",
    "        D_trainer.train_minibatch(input_map)\n",
    "        D_progress_printer.update_with_trainer(D_trainer)\n",
    "        \n",
    "    # train G\n",
    "    k = 1\n",
    "    G_mb = next(G_DS)\n",
    "    input_map = {G_feature_z: G_mb[0], G_feature_code: G_mb[1]}\n",
    "    for i in range(k):\n",
    "        G_trainer.train_minibatch(input_map)\n",
    "        G_progress_printer.update_with_trainer(G_trainer)\n",
    "\n",
    "    if epoch % 100 == 99:\n",
    "        D_progress_printer.epoch_summary()\n",
    "        G_progress_printer.epoch_summary()\n",
    "        visualize(epoch)\n",
    "print('training conditional DCGAN takes {}(secs) long'.format(time.time() - t0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "<h2>visualize generator</h2>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/aj/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/core.py:361: UserWarning: your data is of type \"float64\", but your input variable (uid \"Input3\") expects \"<class 'numpy.float32'>\". Please convert your data beforehand to speed up training.\n",
      "  (sample.dtype, var.uid, str(var.dtype)))\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n0NBQNG7cWNb675abmxvy8/MhiiL8/f0B/F9cB6VSJ02YMAG5ublo2rSp7eGvX78+Ro8ejWrVquHQ\noUOy7knWaDSYO3cubt68if3790MURXTr1g0uLi74f+2deVBTV//Gvzc3QsKmIO4rigzqCLhhBfdd\nW61VBBF0tNba4tbRFpGK03m1OAzVTl2gMmid7ihWK4gKVmspIgUVURC1LCoqiuwQkpDkef/gZ37S\nyiJv7g1pz2cmf5DJ5PvknHse7j333PNkZmaKHjB8//59Sk9PJysrKzpx4gRt2LCBampqaPPmzXTj\nxg1atGhRo/XjQtG/f3+Kjo4mX19funbtGoWGhtKqVato2rRpVFJSQjzPU11dHcXFxQm6N8yYMWOo\ntraWdu3aRV27dqWtW7eStbU1rV69WrCaLZGWlkaPHz8mKysr2rFjB3l6eooW1denTx969OgRPXr0\niGxtbUkqldJbb71Fjo6OdOHCBdq7d69hlj+2+fqgjVAzlyo9e/ZEXl4eLl68iOLiYhQWFqK6uhqr\nV69uchLfkDokEgl2796Nu3fvIiYmBpGRkTh69CgePHgAnU6HpUuXinq5N3ToUJw/fx4qlQo6nQ6n\nTp1C586dRbvcMzMzQ3R0NPLz83HgwAFEREQgLS0NdXV1qKiogJ2dneA6unTpgm+//Raff/45tm/f\njqysLAQHBze51FDoftmxYwd27twJlUqFuro65OfnIyAgANbW1qLqGDlyJDZu3AitVguNRgONRqM/\nTmJjY7F48WLBdfTs2RO//fYbzp8/j6SkJDx69AihoaGN7keJOV6IGp4WzczMRGFhIZ4+fYrr16+L\ntoqF4zhERETg+vXrSEhIwL59+5CSkoLNmze3OJX3SrXbrLqNNCec4zi89957qK6u1n++srKy2Zsa\nhtbB87x+s6obN26gtrYWOp0OVVVVTa45FfIgHDJkCA4cOIDjx483uW+BkDokEgnq6+uh0+mgUqn0\nBvH666+LooPneezevRubNm3C0aNHUVBQ0OTNPrH6Zfbs2Vi1ahV69OjRKoMSSoednR0yMjJw9+5d\nXL16Vd8+U6ZMEUVHnz59MG7cOOTl5SE3Nxeenp6tujks5Hjp1asXQkJCsHDhQhw+fLjZFRuG1sFx\nHKysrKBQKFBRUYGgoCDMnj272Rv2bdEherBvay/tLSwsSK1Wt7gda1vlt1bH88+1VEdoHa1FKB08\n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\nQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f7e4c0a1da0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# sampling from generator\n",
    "sample_codes = enc.transform(np.arange(10).repeat(10)[:, None])\n",
    "sample_z = np.random.normal(0, .33, (100, 100))\n",
    "fake_images = G_net.eval({G_feature_z: sample_z, G_feature_code: sample_codes}, outputs=G_net.G_out)\n",
    "\n",
    "\n",
    "def plot_images(images, subplot_shape):\n",
    "    '''\n",
    "    depict images in a single plot\n",
    "\n",
    "    Args:\n",
    "        images: np.array of images\n",
    "        subplot_shape: layout of subplot\n",
    "    '''\n",
    "    plt.style.use('ggplot')\n",
    "    fig, axes = plt.subplots(*subplot_shape)\n",
    "    for image, ax in zip(images, axes.flatten()):\n",
    "        ax.imshow(image.reshape(img_w, img_h), vmin=-1., vmax=1., cmap='gray')\n",
    "        ax.axis('off')\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "plot_images(fake_images, [10, 10])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [cntk-py35]",
   "language": "python",
   "name": "Python [cntk-py35]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
